package orm

import (
	"github.com/prometheus/client_golang/prometheus"
	"gorm.io/gorm"
	gormprometheus "gorm.io/plugin/prometheus"
)

const _mysqlNamespace = "mysql"

var (
	_mySQLMetricRequests = prometheus.NewCounterVec(prometheus.CounterOpts{
		Namespace: _mysqlNamespace,
		Subsystem: "requests",
		Name:      "cmd_total",
		Help:      "The total number of processed requests",
	}, []string{"database", "name", "service_id", "service_instance", "table", "cmd"})
)

type RequestMetrics struct {
	Database        string
	InstName        string
	ServiceID       string
	ServiceInstance string
}

func (m *RequestMetrics) Metrics(p *gormprometheus.Prometheus) []prometheus.Collector {
	m.collect(p)
	collectors := make([]prometheus.Collector, 0, 1)
	collectors = append(collectors, _mySQLMetricRequests)
	return collectors
}

// 收集 gorm DB的CRUD操作数据
func (m *RequestMetrics) collect(p *gormprometheus.Prometheus) {
	_ = p.DB.Callback().Query().After("gorm:query").Register("after:query", func(db *gorm.DB) {
		cmd := ""
		if len(db.Statement.BuildClauses) > 0 {
			cmd = db.Statement.BuildClauses[0]
		}
		_mySQLMetricRequests.WithLabelValues(m.Database, m.InstName, m.ServiceID, m.ServiceInstance, db.Statement.Table, cmd).Inc()
	})
	_ = p.DB.Callback().Create().After("gorm:create").Register("after:create", func(db *gorm.DB) {
		cmd := ""
		if len(db.Statement.BuildClauses) > 0 {
			cmd = db.Statement.BuildClauses[0]
		}
		_mySQLMetricRequests.WithLabelValues(m.Database, m.InstName, m.ServiceID, m.ServiceInstance, db.Statement.Table, cmd).Inc()
	})
	_ = p.DB.Callback().Update().After("gorm:update").Register("after:update", func(db *gorm.DB) {
		cmd := ""
		if len(db.Statement.BuildClauses) > 0 {
			cmd = db.Statement.BuildClauses[0]
		}
		_mySQLMetricRequests.WithLabelValues(m.Database, m.InstName, m.ServiceID, m.ServiceInstance, db.Statement.Table, cmd).Inc()
	})
	_ = p.DB.Callback().Delete().After("gorm:delete").Register("after:delete", func(db *gorm.DB) {
		cmd := ""
		if len(db.Statement.BuildClauses) > 0 {
			cmd = db.Statement.BuildClauses[0]
		}
		_mySQLMetricRequests.WithLabelValues(m.Database, m.InstName, m.ServiceID, m.ServiceInstance, db.Statement.Table, cmd).Inc()
	})
	_ = p.DB.Callback().Row().After("gorm:row").Register("after:row", func(db *gorm.DB) {
		cmd := ""
		if len(db.Statement.BuildClauses) > 0 {
			cmd = db.Statement.BuildClauses[0]
		}
		_mySQLMetricRequests.WithLabelValues(m.Database, m.InstName, m.ServiceID, m.ServiceInstance, db.Statement.Table, cmd).Inc()
	})

	_ = p.DB.Callback().Raw().After("gorm:raw").Register("after:raw", func(db *gorm.DB) {
		cmd := ""
		if len(db.Statement.BuildClauses) > 0 {
			cmd = db.Statement.BuildClauses[0]
		}
		_mySQLMetricRequests.WithLabelValues(m.Database, m.InstName, m.ServiceID, m.ServiceInstance, db.Statement.Table, cmd).Inc()
	})

	_ = prometheus.Unregister(_mySQLMetricRequests)
	return
}
